﻿using Com.Lancetinc.Evs.Helpers;
using NLog;
using System;
using System.ComponentModel;
using System.Threading.Tasks;
using System.Windows;

namespace Com.Lancetinc.Evs.Windows
{
    public interface IProgressController : IDisposable
    {
        public event EventHandler OnDisposed;

        bool IsDisposed { get; }

        /// <summary>
        /// 标题
        /// </summary>
        string WaitTitle { get; set; }

        /// <summary>
        /// 消息内容
        /// </summary>
        string Message { get; set; }

        /// <summary>
        /// 进度0-100
        /// </summary>
        int Progress { get; set; }
    }

    /// <summary>
    /// ProgressWindow.xaml 的交互逻辑
    /// </summary>
    public partial class ProgressWindow : IWaitBox, IProgressController
    {
        private static readonly ILogger Logger = LogManager.GetCurrentClassLogger();
        private readonly TaskCompletionSource<IProgressController> _loadWaiter = new();
        public ProgressWindow()
        {
            InitializeComponent();
            this.Owner = Application.Current.MainWindow;
            this.ContentRendered += WaitBoxWindow_ContentRendered;
            this.Closed += ProgressWindow_Closed;
        }

        private void ProgressWindow_Closed(object sender, EventArgs e)
        {
            if (!_disposed)
                Dispose();
        }

        private void WaitBoxWindow_ContentRendered(object sender, EventArgs e)
        {
            PgbProgressBar.IsIndeterminate = !ShowProgress;
            _loadWaiter.SetResult(this);
        }

        protected override void OnClosing(CancelEventArgs e)
        {
            base.OnClosing(e);
            if (_disposed || e.Cancel)
            {
                return;
            }

            if (CanCancel)
            {
                Canceled = true;
                return;
            }

            e.Cancel = true;
        }

        #region IWaitBoxInitializer, IWaitBoxProcessing

        public string WaitTitle
        {
            get => Title;
            set
            {
                WpfHelper.ExecSafe(() => this.Title = value);
            }
        }

        private int _progress = 0;
        public event EventHandler OnDisposed;

        public string Message
        {
            get => TxbDescription.Text;
            set
            {
                WpfHelper.ExecSafe(() => TxbDescription.Text = value);
            }
        }

        public int Progress
        {
            get => _progress;
            set
            {
                _progress = Math.Min(value, 100);
                WpfHelper.ExecSafe(() =>
                {
                    if (PgbProgressBar.IsIndeterminate)
                        PgbProgressBar.IsIndeterminate = false;
                    PgbProgressBar.Value = _progress;
                });
            }
        }

        public bool CanCancel
        {
            get;
            private set;
        }

        /// <summary>
        /// 是否需要更新进度
        /// </summary>
        public bool ShowProgress { get; private set; }

        public bool Canceled
        {
            get;
            private set;
        }

        public Task<IProgressController> ShowAsync(string title, string message, bool canCancel, bool showProgress)
        {
            this.CanCancel = canCancel;
            if (!canCancel)
            {
                BtnCancel.Visibility = Visibility.Collapsed;
                ShowCloseButton = false;
            }

            this.ShowProgress = showProgress;
            if (!showProgress)
            {
                PgbProgressBar.Visibility = Visibility.Collapsed;
            }
            this.WaitTitle = title;
            this.Message = message;
            Logger.Info($"{GetHashCode()},[{title}],{Message}");

            // 关闭的时候确保Dispose被调用
            this.Closed += (s, e) =>
            {
                this.Dispose();
            };
            WpfHelper.ExecLater(() =>
            {
                if (_disposed)
                    return;

                ShowDialog();
            });
            return _loadWaiter.Task;
        }

        #endregion IWaitBoxInitializer, IWaitBoxProcessing

        public bool IsDisposed => _disposed;

        private bool _disposed = false;
        public void Dispose()
        {
            if (_disposed)
                return;
            _disposed = true;
            this.Close();
            OnDisposed?.Invoke(this, EventArgs.Empty);
        }
    }

    public interface IWaitBox
    {
        /// <summary>
        /// 显示等待框，Dispose之后关闭等待框
        /// </summary>
        /// <returns></returns>
        Task<IProgressController> ShowAsync(string title, string message, bool canCancel = false, bool showProgress = false);
    }

    public static class WaitBoxHelper
    {
        public static IWaitBox WaitBox => new ProgressWindow();
    }
}